/**********************************************************
                     cor.c
written by IL
seriously edited by CAS

read and writes the fpc .cor file
Cari - 12/24/03 add checks for Zbatch_flag so will not write message on batch
***********************************************************/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <limits.h>
#include "fpp.h"
#include "dirent.h"
#include "glib_port.h"

/*efriedr*/
#define graphQuery messQuery

#ifdef ALPHA
#include <sex.h>
#endif
#ifdef X86
#include <byteswap.h>
#endif

extern int save_fpc();
extern void grantaccess();
extern int Zbatch_flag;
extern void recalccontigs(), recalcparents(), markersetzero(), markercorrect();
extern FILE *graphQueryOpen();
extern BOOL filCheck();
extern void settime();
extern int fppFind_NoSort();
extern int lexstrcmp_fpc(a,b);

int rebuild_cor_flag = 0;

void overwritebands(FILE *bandfile, int b1, int b2 ,int index);
/* sness */
void suffixremove(char*);

static int Total, TotalClones;
static  FILE *corfile;
static char clonecheck[54];
static int ForceUpdate=FALSE, SizeFile=FALSE;
static char subDir[20]; /* contains Bands or Sizes */
static int nextBand;
static int bandCountFlag=0;

int clone_compare (const void* a, const void* b);
BOOL fppInsert_NoSort(Array a, char *s, int *index, BOOL (*order)());
struct hash_list_element* clone_hash_table[HASH_SIZE];
unsigned int hash_clone(char* name);
void initialize_hash_table();
void add_to_hash(unsigned int hash, int i);

typedef struct orclone
{
  int b1,b2; 
  int cloneindex;
  char gelname[GEL_SZ]; /* which gel it is */
} B1S;

/*********************************************************************
                 DEF: Do_conversions
*********************************************************************/
static void Do_conversions(CLONE *clone)
{
  clone->class = TYPEBAC;
#ifdef SANGER
  if(clone->clone[0] == 'y') clone->class = TYPEYAC;
  else if (clone->clone[0] == 'b') clone->class = TYPEBAC;
  else if (clone->clone[0]== 'd') clone->class = TYPEPAC;
  else if(clone->clone[0]== 'c') clone->class = TYPECOSMID;
  else if(clone->clone[0]== 'f') clone->class = TYPEFOSMID;
  else if(clone->clone[0]== 'N') clone->class = TYPEBAC;
  else clone->class = TYPECLONE;
#endif
  strcpy(clone->fp->fpchar,"   ");
}

/***********************************************************
                DEF: fpRead
read .cor file
**********************************************************/
//
// Cor files can have either 2 or 4-byte bands, always in BIG-ENDIAN order. 
//
int fpRead()
{
  int *vp;
  unsigned int nb,size = sizeof(int), swap=0, zero=0;
  FILE *corfile;
  int i, j, k;
  char fileTemp[FIL_BUFFER_SIZE] ;
  char dirTemp[DIR_BUFFER_SIZE] ;
  CLONE *clone;

  if (size != 4) {
     printf("int not 4 bytes; cannot load .cor\n");
     return -1;
  }

  if (arrayExists(bands)) return 0;
  strcpy(fileTemp, fileName);
  strcpy(dirTemp, fileTemp);

  if(strlen(dirName)>0){
    if((corfile = fopen(messprintf("%s/%s.cor", dirName, fileName),"rb")) == NULL ){
      printf("*** File %s/%s.cor does not exist.\n",dirName, fileName);
      if (!(corfile = graphQueryOpen(dirTemp, fileTemp, "cor", "rb", 
				  "Project .cor file"))){
	displaymess("NO .cor file read. Therefore no finger prints.");
	return -1;
      }
	  /* sness */
	  suffixremove(fileTemp);
    }
  }
  else{
    if((corfile = fopen(messprintf("%s.cor", fileName),"rb")) == NULL ){
      printf("*** File %s.cor does not exist.\n", fileName);
      if (!(corfile = graphQueryOpen(dirTemp, fileTemp, "cor", "rb", 
				  "Project .cor file"))){
	displaymess("NO .cor file read. Therefore no finger prints.");
	return -1;
      }
	  suffixremove(fileTemp);
    }
  }
  fseek(corfile, 0, SEEK_END);
  nb = ftell(corfile);
  rewind(corfile);

  bands = arrayCreate(num_of_bands, int);
  arrayMax(bands) = num_of_bands;
  vp = arrp(bands, 0, int);

  if (nb == sizeof(int)*num_of_bands){
  	if ((i=fread(vp,size,nb,corfile)) != num_of_bands) {
     	fprintf(stderr,"Error: cannot read 4-byte cor file %d %d\n",nb, i);
     	return -1;
  	}
      for(i=0;i<arrayMax(bands);i++) {
           vp[i] = SWAP_HALF(vp[i]);
      }
  }
  else if (nb == sizeof(short)*num_of_bands) {
     // cor file has shorts; two-step load
     unsigned short* tbands = (unsigned short*)malloc(num_of_bands*sizeof(unsigned short));
     i = fread(tbands,sizeof(unsigned short),num_of_bands,corfile);
     if (i != num_of_bands) {
     	fprintf(stderr,"Error: cannot read 2-byte cor file %d %d\n",num_of_bands, i);
     	return -1;		
     }
     for (i = 0; i < num_of_bands; i++) {
		unsigned short band = SWAP_HALF16(tbands[i]);
		//printf("before:%d \t after:%d\n",tbands[i],band);fflush(0);
        vp[i] = band;
     }
     free(tbands);
  }
  else {
     nb *= size;
     printf("Unable to tell .cor file type: .cor has %d bytes, .fpc file has %d bands\n",
            nb,num_of_bands);
	 return -1;

  }

  filclose(corfile);
  corfile = 0;    

  bandmax = 0;
  bandmin = INT_MAX;

  for(i=0;i<arrayMax(bands);i++) {
       bandmax = MaX(bandmax, vp[i]);
       bandmin = MiN(bandmin, vp[i]);
  }
  fprintf(stdout, "Read %d bands from .cor file. Band range(%d %d).\n",
            arrayMax(bands), bandmin, bandmax);
  fflush(stdout); /* cari 2/4/4 for cronjob */

/* check for corrupted file */
  for (j=i=0; i<arrayMax(acedata); i++) {
    clone = arrp(acedata, i, CLONE);
    if (clone->fp == NULL) continue;
    if (clone->clone[0] == '!') continue;
    if (clone->fp->b2 == 0) continue;

    if (clone->fp->b1 > nb) {
       fprintf(stderr,"Fatal error: clone has offset %d past end of cor file %d.\n",
                clone->fp->b1, nb);
       exit(1);
    }
    if (clone->fp->b2 > NBANDS ) {
      fprintf(stderr,"Fatal error: clone has %d bands,  limit is %d/\n",
	      clone->fp->b2,NBANDS);
      exit(1);
    }
    for (k=j=0; j< clone->fp->b2-1; j++) {
/*
      if (vp[clone->fp->b1+j-1] < 0) {
           if (k==0) {
             k=clone->fp->b1+j-1; 
             fprintf(stderr,"Negative band %6d: %-14s Gel %10s %d/%d/%d\n",
                   vp[k], clone->clone, clone->fp->gelname, clone->creation_date.day,
                   clone->creation_date.month, clone->creation_date.year);
           }
           zero++;
      }
      else 
*/
	//printf("%s %d\n",clone->clone,vp[clone->fp->b1 + j - 1]); fflush(0);
      if (vp[clone->fp->b1 + j - 1] > vp[clone->fp->b1+j]) {
           if (k==0) {
             k=clone->fp->b1+j-1; 
             fprintf(stderr,"Wrong order %6d %6d: %-14s Gel %10s %d/%d/%d\n",
                   vp[k], vp[k+1],
                   clone->clone, clone->fp->gelname, clone->creation_date.day,
                   clone->creation_date.month, clone->creation_date.year);
           }
           swap++;
           if (swap > 20) {
               fprintf(stderr,"Fatal Update .cor error: too many incorrect bands\n");
               break;
           }
      }
    }
  }
  if (swap > 0 || zero>0){
    fprintf(stderr,
     "\nCor file %d wrong order, %d less zero (only one message per clone written)\n", 
      swap, zero);
    fprintf(stderr, "Use File.., Check cor, enter clone name in yellow box to see bands\n");
    fprintf(stderr, "You probably need to Cancel the bad clones\n\n");
  }
  return 1;
}

/*****************************************************************
                DEF: checkdirstruct
*****************************************************************/
static void checkdirstruct()
{
  char str1[MAXPATHLEN], str2[MAXPATHLEN];

  if(strlen(dirName)>0) sprintf(str1,"%s/%s",dirName, subDir);
  else strcpy(str1,subDir);

  if(!filCheck(str1,"d")){
    sprintf(str2,"mkdir %s", str1);
    printf("Adding directory %s\n", str1);
    system(str2);
  }
}
/*****************************************************************
                DEF: checkoutfile
read though file to make sure its ok, else reject the whole thing
*****************************************************************/
BOOL checkoutfile(char *imageDir,char *filename)
{
  FILE *bandfile;
  char str1[MAXPATHLEN+100];
  char clonename[256]; /* make large case clone name is too big */
  BOOL header, rc=TRUE, found;
  int bandcount=0,band=0,icount=0;
  char gelname[256], junk[256]; /*make gel name large too */
  struct fpdata *fpdata;
  int cntbands=0, cnt=0, index;
  int i, last_band=0, cntclones=0, cntrepeat=0;
  CLONE *clp;

  sprintf(str1, "%s/%s", imageDir, filename);
  if((bandfile = fopen(str1,"r")) == NULL ){
      printf("Error opening file %s\n",str1);
      return FALSE;
  }
    
  header = TRUE;
  while(fgets(junk,255,bandfile) != NULL){
      cnt++;
      if(header){
	 header = FALSE;
         found=FALSE;
         last_band=0;
	 if(sscanf(junk,"%s %d %s",clonename,&bandcount,gelname) != 3){
	    printf("ERROR Line %d Should be: clonename  bandcount  gelname\n", cnt);
	    printf("But line reads \"%s\"\n",junk);
	    rc= FALSE;
	 }
          /* 9 may 03 CAS - was not checking length of clone name */
	 sscanf(junk,"%s %d %s",clonename,&bandcount,gelname);
         if (strlen(clonename) > CLONE_SZ) {
            printf("Clone %s name too long -- max %d\n",clonename, CLONE_SZ);
	    rc= FALSE;
         }
         else if (strlen(gelname) > GEL_SZ) {
            printf("Gel %s name too long -- max %d\n",gelname, GEL_SZ);
	    rc= FALSE;
         }
         cntclones++;
         found=TRUE;

	 if(fppFind_NoSort(acedata,clonename,&index,cloneOrder)){

            for (fpdata = arrp(acedata, index, CLONE)->fp; 
	        fpdata != NULL && !found; fpdata = fpdata->next)
            {
	        if(strcmp(fpdata->gelname,gelname)!=0) continue;
                found = TRUE;
                
	        if(!ForceUpdate){
                    cntrepeat++;
                    continue;
	        }
                     /* force update; from File..., Check cor */
                header = TRUE;
                rc = FALSE;
                if (bandcount > fpdata->b2) {
                    printf("%s cannot force update more bands %d %d\n",
                          clonename, fpdata->b2, bandcount);
                }
                else {
                    i= -1;
                    while(fgets(junk,255,bandfile) != NULL){
                          sscanf(junk,"%d",&band);
                          if (band == -1) break;
                          array(bands,fpdata->b1+i,int) = band;
                          i++;
                    }
                    fpdata->b2 = bandcount;
	            clp = arrp(acedata, index, CLONE); 
	            settime(&clp->modified_date);
                    TotalClones++;
		}
	    } 
	} 

        if (ForceUpdate && !found) printf("No clone %s in FPC\n",clonename);
        else if (!found && rc) cntbands += bandcount;

        if (bandcount > NBANDS) {
	    printf("ERROR %s bandcount = %d exceeded band limit of %d\n",
               clonename, bandcount, NBANDS);
            rc = FALSE;
        }
        continue;
      }

      sscanf(junk,"%d",&band);
      if(band == -1){
         header = TRUE;
	 if(bandcount != icount){
	      printf("Warn: %s bandcount = %d, but number counted  = %d\n",
                 clonename, bandcount,icount);
              
              if (bandCountFlag==0) {
                 if (graphQuery(
               "Answer\nYes: Ignore files with bandcount error.\nNo:  Process all files.")) 
                           bandCountFlag=1;
                 else bandCountFlag=2;
              }
              if (bandCountFlag==1) rc=FALSE;
	  }
	  icount = 0;
          continue;
       }

       if (band < 0) {
	      printf("\nERROR gel %s clone %s negative band value %d\n", 
                    gelname, clonename, band);
	      rc = FALSE;
       }
       else if (band > INT_MAX && SizeFile==FALSE) {
	      printf("\nERROR gel %s clone %s band value %d > limit (%d)\n", 
                    gelname, clonename, band, INT_MAX);
	      rc = FALSE;
       }
       else if (band < last_band) {
	   printf("\nERROR gel %s clone %s bands in wrong order %d %d - abort immediately\n", 
                    gelname, clonename, last_band, band);
	      return FALSE; /* whole gel may be in wrong order */
       }
       last_band = band;
       icount++;
   }
   fclose(bandfile);
   if (cntrepeat > 0 && cntrepeat==cntclones) {
      printf("ERROR File %s has %d out of %d gel entries already in fpc - ignore file\n",
             filename, cntrepeat, cntclones);
      rc = FALSE;
   }
   else if (cntrepeat > 0 && rc!=FALSE) {
      printf("WARNING File %s has %d out of %d gel entries already in fpc - continuing\n",
             filename, cntrepeat, cntclones);
   }
   if (rc) arrayExtend(bands,nextBand+cntbands); 
   return rc;
}

/*************************************************************
           DEF: initialize_hash_table()
           W.Nelson 12/03
           put the existing clones into the table
*************************************************************/
void initialize_hash_table()
{
   int i;
   unsigned int hash;

   for (i = 0; i < HASH_SIZE; i++)
   {
      clone_hash_table[i] = 0;
   }

   for (i = 0; i < arrayMax(acedata); i++)
   {
      hash = hash_clone(arrp(acedata, i, CLONE)->clone);
      add_to_hash(hash,i); 
   }
}
/*************************************************************
           DEF: readBandsFile
*************************************************************/
BOOL readBandsFile(char *imageDir,char *filename)
{
  FILE *bandfile;
  char str1[MAXPATHLEN],str2[MAXPATHLEN], str3[MAXPATHLEN*2];
  char clonename[CLONE_SZ],junk[256];
  BOOL header, allowed;
  int jj;
  int  count=0,bandcount=0,band=0;
  char gelname[GEL_SZ+1];
  CLONE *clone=NULL,setclone;
  struct fpdata *fpdata,*tempfp;
  int  cnt, index;
  FILTER *filter;

  sprintf(str1,"%s/%s",imageDir, filename);
  if(!checkoutfile(imageDir,filename)){
     if (!ForceUpdate) printf("File %s not added to cor.\n\n", str1);
     else {Total++;}
     return 0;
  }
  cnt=0;
    
  if(strlen(dirName)>0) sprintf(str2,"%s/%s/%s",dirName, subDir, filename);
  else sprintf(str2,"%s/%s", subDir, filename);

  count = 0;
  if((bandfile = fopen(str1,"r")) == NULL ){
      printf("Error opening file %s\n",str1);
      return FALSE;
  }

  header = TRUE;
  while(fgets(junk,255,bandfile) != NULL)
  {
     if(header) 
     {
	if(filterdata){
	  for(jj=0;jj<arrayMax(filterdata);jj++){
	    filter = arrp(filterdata,jj,FILTER);
	    filter->done= FALSE;
	  }
	}
	if(sscanf(junk,"%s %d %s",clonename,&bandcount,gelname)==3){
	  if(!fppInsert_NoSort(acedata,clonename,&index,cloneOrder)){                 
	      clone = arrp(acedata, index, CLONE);    /* get original clone */
	      for (jj=0,fpdata = clone->fp; fpdata != NULL && jj==0; fpdata = fpdata->next ) {
		     if(strcmp(fpdata->gelname,gelname)==0){
		        while(fgets(junk,255,bandfile) != NULL) {
		           sscanf(junk,"%d",&band);
		           if(band == -1) break;
		        } 
		        jj = 1;
		      }
	      }
	      if (jj==1) continue;

	      if (!Zbatch_flag && !rebuild_cor_flag)
                 printf("Clone %s already exists. Adding new fingerprint for gel %s\n",
		 clonename,gelname);
	      settime(&clone->modified_date);
	      tempfp = clone->fp;
	      clone->fp = (struct fpdata *)messalloc(sizeof(struct fpdata));
	      fpdata = clone->fp;
	      strcpy(fpdata->fpchar,"   ");
	      strcpy(fpdata->gelname, gelname); 
	      if(bandcount) fpdata->b1= nextBand+1;
	      else fpdata->b1 = nextBand;
	      fpdata->b2 = 0;
	      fpdata->next = tempfp;
	  }
	  else{
          if (rebuild_cor_flag == 1) {
             printf("Fatal Error: Clone %s not found in FPC project\n",clonename);
             fflush(0); exit(0);
		     while(fgets(junk,255,bandfile) != NULL) {
		        sscanf(junk,"%d",&band);
		        if(band == -1) break;
		     } 
             continue;
          }
          else {
	         strcpy(setclone.clone,clonename);
	         array(acedata,index,CLONE) = setclone;
	         clone = arrp(acedata,index,CLONE);
	         clone->fp = (struct fpdata *)messalloc(sizeof(struct fpdata));

	         Do_conversions(clone);

	         clone->remark = clone->fp_remark = NULL;
	         clone->mattype = 0;
	         clone->seq_hits = 0;
	         clone->next = -1;
	         clone->parent = -1; 
	         clone->ctg = clone->oldctg = clone->x = clone->y = clone->highcol=0;
             clone->size_bp = 0;
	         clone->ibc=0;
	         strcpy(clone->chctg,"        ");          
	         clone->marker = NULL;
	         clone->selected = FALSE;
	         clone->seqstat = clone->seqtype = 0;
	         settime(&clone->creation_date); 
	         settime(&clone->modified_date);  /* 22 nov 98 - for year 2000 */
	         strcpy(clone->match,"          ");

	         strcpy(clone->fp->gelname, gelname); 
	         if(bandcount) clone->fp->b1= nextBand+1;
	         else clone->fp->b1 = nextBand;
	         clone->fp->b2 = 0;
	         clone->fp->next = NULL;
         }
	  }
	  cnt += bandcount;
	  count++;
	  header = FALSE;
	  continue;
        }
      } 
         /* finish clone */
      sscanf(junk,"%d",&band);
      if(band == -1){
	  header = TRUE;
          continue;
      }
      else if(clone!=NULL) clone->fp->b2++;

         /* process band */
      if(filterdata && clone!=NULL){
         allowed = TRUE;
	 for(jj=0;jj<arrayMax(filterdata);jj++){
	     filter = arrp(filterdata,jj,FILTER);
	     if((clone->class == filter->type) && !filter->done && allowed){
	        if(filter->subtype == '0' ||   
	          (filter->subtype == clone->clone[1]) || 
		  (filter->subtype == '*' && 
                   (!strchr(filter->exclude,clone->clone[1]))))
                  {  
		      if(band >= filter->min && band <= filter->max){
		        filter->done= TRUE;
		        allowed = FALSE;
		      }
		  }
	     }
	  }
	  if (!allowed) {
		clone->fp->b2--;
                continue;
	  }
      }
      if (band > INT_MAX) { 
	  printf("Warn %s band value %d > limit (%d) - Add fp_remark and band=%d\n", 
                      clonename, band, INT_MAX, INT_MAX);
          if(clone!=NULL){
	    clone->fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
	    sprintf(clone->fp_remark->message, "OverMax %d",band);
	    clone->fp_remark->next = NULL;
          }
          band = INT_MAX;
      }
      array(bands,nextBand++,int) = band;
      if(band > bandmax) bandmax = band;
   }
    
   fclose(bandfile);
   num_of_bands = nextBand;
   Total += cnt;
   TotalClones+= count;
       /* ADD 1 apr 99 - for GSC, partial band file could exist */
   if (access(str2, F_OK)==0) {
     if (!Zbatch_flag)
        printf("Append %s: added %d clones %d bands.\n",str1,count, cnt);
     sprintf(str3,"cat %s >> %s",str1,str2);
     system(str3);
     sprintf(str3,"rm %s",str1);
     system(str3);
   }
   else {
     if (!Zbatch_flag)
        printf("File %s: added %d clones %d bands.\n",str1,count, cnt);
     sprintf(str3,"mv %s %s",str1,str2);
     system(str3);
   }
return TRUE;
}

/********************************************************
             DEF: hash_clone
             W. Nelson 11/03
*******************************************************/
unsigned int hash_clone(char* name)
{
    char* pc;
    char ch;
    unsigned int hash;

    pc = name;
    hash = 1;

    while (*pc)
    {
        ch = tolower(*pc);  /* clone names can appear with different cases*/
        hash *= (unsigned int)(ch);
        hash += 17;
        hash %= HASH_SIZE;
        pc++;
    }
    return hash;
}
/********************************************************
             DEF: add_to_hash
             W. Nelson 11/03
*******************************************************/
void add_to_hash(unsigned int hash, int i)
{
    struct hash_list_element *new;
    struct hash_list_element *old_first;

    new = malloc(sizeof(struct hash_list_element));
    new->i = i;

    /* insert the new element at the beginning for simplicity */
    old_first = clone_hash_table[hash];
    clone_hash_table[hash] = new;
    new->next = old_first;
}

/********************************************************
             DEF: destroy_hash
             W. Nelson 11/03
*******************************************************/
void destroy_hash()
{
    int i,j;
    struct hash_list_element *this;
    struct hash_list_element *next;

    for (i = 0; i < HASH_SIZE; i++)
    {
        this = clone_hash_table[i];
        while(this)
        {
            next = this->next;
            j = this->i;

            free(this);
            this = next;
        }  
        clone_hash_table[i] = 0;     
    }
}

/********************************************************
             DEF: readImageDir
*******************************************************/
BOOL readImageDir(char *imageDir)
{
  int len, nfiles=0;
  struct stat stbuf;
  DIR *dfd;
  struct dirent *dp2;
  int first_band=1, first_size=1;
  void* array_start;

  initialize_hash_table();

  nextBand = arrayMax(bands);

  bandCountFlag=0;
  TotalClones=Total=0;
  if(stat(imageDir, &stbuf) == -1){
    printf("Cannot access %s\n",imageDir);
    return FALSE;
  }
  if( (dfd = opendir(imageDir)) == NULL){
      printf("Error cannot open %s\n",imageDir);
      return FALSE;
  }
  while (( dp2 = readdir(dfd)) != NULL) {
      if(strcmp(dp2->d_name,".") == 0
	 || strcmp(dp2->d_name,"..") == 0)
	continue;
      len = strlen(dp2->d_name);
      if(strncasecmp(&dp2->d_name[len-6],".bands",6)==0){
          if (first_size==0) {
              printf("Processing size files - ignoring %s\n", dp2->d_name);
              continue;
          }
          strcpy(subDir,"Bands");
          if (first_band) {
              first_band=0;
              checkdirstruct();
          } 
          SizeFile=FALSE; 
      }
      else if(strncasecmp(&dp2->d_name[len-6],".sizes",6)==0){
          if (first_band==0) {
              printf("Processing band files - ignoring %s\n", dp2->d_name);
              continue;
          }
          strcpy(subDir,"Sizes");
          if (first_size) {
              first_size=0;
              checkdirstruct();
          } 
          SizeFile=TRUE; 
      }
      readBandsFile(imageDir,dp2->d_name);
      nfiles++;
  } 
  closedir(dfd);
  filclose(corfile);
  corfile = 0;

  printf("Read %d files. Add %d gel entries and %d bands.\n",nfiles,TotalClones, Total);
  
  fflush(stdout);
  destroy_hash();
  array_start = arrp(acedata, 0, CLONE);
  qsort(array_start, arrayMax(acedata), acedata->size, clone_compare);

  return TRUE;
}

/*********************************************************
                DEF: clone_compare
                W. Nelson 11/03
*********************************************************/
int clone_compare (const void* a, const void* b)
{
    return lexstrcmp_fpc(((CLONE*)a)->clone, ((CLONE*)b)->clone);
}

/*********************************************************
                DEF: createnewcor
*********************************************************/
//
// Write out the bands in BIG-ENDIAN order
//
BOOL createnewcor()
{
  char str1[MAXPATHLEN*2];
  int *tmp;
  int i;

  if(strlen(dirName)>0){
     sprintf(str1,"mv %s/%s.cor %s/%s.cor.backup", dirName, fileName,
	       dirName, fileName);
     system(str1);
     if((corfile = fopen(messprintf("%s/%s.cor", dirName, fileName),"w")) == NULL )
	return FALSE;
   }
   else{
      sprintf(str1,"mv %s.cor %s.cor.backup", fileName, fileName);
      system(str1);
      if((corfile = fopen(messprintf("%s.cor", fileName),"w")) == NULL )
	return FALSE;
   }

   tmp = (int *) malloc(sizeof(int) * arrayMax(bands));

    for (i=0; i< arrayMax(bands); i++) {
      tmp[i] = SWAP_HALF(arr(bands, i, int));
	}

    fwrite(tmp,sizeof(int), arrayMax(bands),corfile);
    free(tmp);
    fclose(corfile);
    corfile = 0;
    
    return TRUE;
}

/*************************************************************
                 DEF: updatecor
called by Update .cor
**************************************************************/
void updatecor()
{
  char imageDir[MAXPATHLEN];

  if(!dataloaded){
    displaymess("No fpc file has been created or read.");
    return;
  }
  displaymess("Update cor:");

  if(!writeaccess){
      grantaccess();
      if(!writeaccess) {
        printf("Cannot update .cor until lock is free\n");
        return;
      }
  } 
  if(fpRead()<0)
    return;

  if(strlen(dirName)>0) sprintf(imageDir,"%s/Image",dirName);
  else sprintf(imageDir,"Image");

  Total = 0;
  readImageDir(imageDir);

  if(Total != 0){
      if(createnewcor())
      {
        if (bands)
	   if (!Zbatch_flag) printf("Cor file has %d bands.\n", arrayMax(bands));
      }
      else printf("Error updating cor file\n");
      recalccontigs(); /* updates singletons */
      recalcparents(); /* don't know why these next 3 are necessary, */
      markersetzero(); /* but something wrong if at least one of the */
      markercorrect(); /* 3 not included, which i'm figuring out which */
      okaytowrite=1;
      save_fpc();
   }
}

/* rebuild the .cor from the band files */
void rebuild_cor()
{
  int i;
  struct fpdata *fp, *fp1;
  CLONE* clp;
  char imageDir[MAXPATHLEN];
  gchar* m;
  int messresult;

  if(!dataloaded){
    displaymess("No fpc file has been created or read.");
    return;
  }
  displaymess("Rebuild cor from files in the Image dir:");

  m = g_strdup_printf("Band files for all clones (and no additional) must be in the Image dir, or FPC will exit and any unsaved changes will be lost.\nContinue?");
  messresult = messQuery(m);
  g_free(m);
  if (messresult == 0) {
     return;
  }

  arrayDestroy(bands);
  bands = 0;
  for (i = 0; i < arrayMax(acedata); i++) {
     clp = arrp(acedata,i,CLONE);
     fp = clp->fp;
     while (fp) {
        fp1 = fp;
        fp = fp->next;
        messfree(fp1);
     }
     clp->fp = 0;   
  }

  if(!writeaccess){
      grantaccess();
      if(!writeaccess) {
        printf("Cannot update .cor until lock is free\n");
        return;
      }
  } 
  if(fpRead()<0)
    return;

  if(strlen(dirName)>0) sprintf(imageDir,"%s/Image",dirName);
  else sprintf(imageDir,"Image");

  Total = 0;
  rebuild_cor_flag = 1;
  readImageDir(imageDir);
  rebuild_cor_flag = 0;

  for (i = 0; i < arrayMax(acedata); i++) {
     clp = arrp(acedata,i,CLONE);
     if (!clp->fp) {
        printf("Fatal Error: No bands found for %s\n",clp->clone);fflush(0);
        exit(0);
     }
  }

  if(Total != 0){
      if(createnewcor())
      {
        if (bands)
	   if (!Zbatch_flag) printf("Cor file has %d bands.\n", arrayMax(bands));
      }
      else printf("Error updating cor file\n");
      recalccontigs(); /* updates singletons */
      recalcparents(); /* don't know why these next 3 are necessary, */
      markersetzero(); /* but something wrong if at least one of the */
      markercorrect(); /* 3 not included, which i'm figuring out which */
      okaytowrite=1;
      save_fpc();
   }
}


/******************************************************************
   The following routines are for Check cor under File...
********************************************************************/
int sortclones(const void *a, const void *b)
{
  if(((struct orclone*)a)->b1 < ((struct orclone*)b)->b1) return -1;
  if(((struct orclone*)a)->b1 > ((struct orclone*)b)->b1) return 1;
  return 0;
}

void createorderedlist()
{
  B1S  *broot;
  int cnt=0, i,j,k=0;
  struct fpdata *fp_ptr;
  int last;
  char prev[200];
  BOOL next=FALSE;

  broot = (struct orclone *)messalloc((sizeof(struct orclone)*arrayMax(acedata)*3));
  for(i=0;i<arrayMax(acedata);i++){
    fp_ptr = arrp(acedata, i, CLONE)->fp;
    j= 0;
    while(fp_ptr != NULL){
      broot[k].b1 = fp_ptr->b1;
      broot[k].b2 = fp_ptr->b2;
      broot[k].cloneindex = i;
      strcpy(broot[k++].gelname, fp_ptr->gelname);
      fp_ptr = fp_ptr->next;
    }
  }
  qsort(broot,k, sizeof(struct orclone), sortclones);
  last = 1;
  strcpy(prev,"*** first\n ");
  for(i=0;i<k;i++){
    if(broot[i].b2==0) continue;
    if(last != broot[i].b1){
      printf("%s",prev);
      if(last > broot[i].b1)
	   printf("*** Olap ");
      else printf("*** Gap  ");      
      printf("%d--->%d\t%13s\t%s\t%2d/%2d/%2d\n\n",broot[i].b1,(broot[i].b1+broot[i].b2-1),
             arrp(acedata,broot[i].cloneindex,CLONE)->clone,broot[i].gelname,
	     arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.day,
             arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.month,
	     arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.year);

      next =TRUE;
      cnt++;
    }
    last = broot[i].b1+broot[i].b2;
    sprintf(prev,"         %d--->%d\t%13s\t%s\t%2d/%2d/%2d\n",
             broot[i].b1,(broot[i].b1+broot[i].b2-1),
             arrp(acedata,broot[i].cloneindex,CLONE)->clone,broot[i].gelname,
	     arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.day,
             arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.month,
	     arrp(acedata,broot[i].cloneindex,CLONE)->creation_date.year);
  }
  printf("Check Cor complete with %d errors.\n",cnt);
  messfree(broot);
}


void cleancor()
{
  Array cleanbands=0;
  int location,orig,b2;
  char gelname[GEL_SZ];
  struct fpdata *fp_ptr,*start,*p=NULL;
  int i,j;
  int temp;
  BOOL first;
  CLONE *clone;

  if(!writeaccess){
      grantaccess();
      if(!writeaccess) return;
  } 
  if(fpRead()< 0 ){
      printf("Error reading cor\n");
      return;
  }
    
  cleanbands = arrayCreate(20,int);
  location = 0;

/* first get rid of clones that have have no fpdata and duplicate fpdata */
/* The following is not ideal in that it does not free the space when the fpdata */
/* modules are removed, but since thiis will be rarely done, so what the heck */

  for(i=0;i<arrayMax(acedata);i++){
      clone =  arrp(acedata, i, CLONE);
      fp_ptr = clone->fp;
      if(fp_ptr != NULL){
	first = TRUE;
	b2 = 0;
        gelname[0] = '\0';
	start = NULL;
	while(fp_ptr != NULL){
	  if((fp_ptr->b2 == b2 && strcmp(fp_ptr->gelname,gelname) == 0) || 
                    (fp_ptr->b2 == 0 && strcmp(fp_ptr->gelname,"0")==0)){
	    printf("%s duplicate fp or zero entry. gel = %s, number of bands = %d\n",
                    clone->clone,gelname,b2);
	  }
	  else{
	    strcpy(gelname, fp_ptr->gelname);
	    b2 = fp_ptr->b2;
	    if(first){
	      start = fp_ptr;
	      p = fp_ptr;
	      first = FALSE;
	    }
	    else{
	      p->next = fp_ptr;
	      p=p->next;
	    }
	  }
	  fp_ptr=fp_ptr->next;
	}
	clone->fp = start;
	p->next = NULL;
      }
   }

/* recreate the bands/cor file with only the clones that now exist */
   for(i=0;i<arrayMax(acedata);i++){
      fp_ptr = arrp(acedata, i, CLONE)->fp;
      while(fp_ptr != NULL){
	orig = fp_ptr->b1;
	fp_ptr->b1 = location+1;
	temp = 0;
	for(j=0;j<fp_ptr->b2;j++){
	  temp  = arr(bands,orig+(j-1),int);	      
	  array(cleanbands,location++,int) = temp;
	}
	fp_ptr = fp_ptr->next;
      }
    }  
    num_of_bands = location; 
    if(!arrayDestroy(bands))
      printf("error destroying old bands\n");
    bands = cleanbands;

    okaytowrite=1;
    if(save_fpc() > 0){
      printf("Fpc file saved\n");
      if(createnewcor())
	printf("Cor file saved\n");
      else
	printf("Error writing cor file!!!!!!\n");
    }
    else
      printf("Problem saving fpc file therefore cor file NOT saved either\n");
}

void getbandsinfo(int index)
{
  CLONE *clone;
  int j;
  struct fpdata *fp_ptr;

  clone = arrp(acedata,index,CLONE);
  printf("%s\n",clone->clone);
  fp_ptr = clone->fp;
  while(fp_ptr != NULL){
    printf("Bands %d  %d  Gel %s\n",fp_ptr->b1,fp_ptr->b2,fp_ptr->gelname);
    for(j=0;j<fp_ptr->b2;j++)
      printf("%d\n",arr(bands,fp_ptr->b1+j-1,int));
    fp_ptr = fp_ptr->next;
  }
}

void printclone(char *temp)
{
  int index;

  if(!bands) /* if no bands then read them in*/
    if(fpRead()< 0 ){
      printf("Error reading cor\n");
      return;
    }
  if(fppFind(acedata,temp,&index, cloneOrder))
    getbandsinfo(index);
  else
    printf("Clone not found\n");
}

void dooverwrite()
{
  ForceUpdate = TRUE;
  updatecor();
  ForceUpdate = FALSE;
}

void debugmenu()
{
  Graph gbands=0;
  int abox;

  gbands = graphCreate (TEXT_SCROLL,"Cor Debug menu",.2,.2,.23,.2) ;

  graphButton("Rebuild .cor",rebuild_cor ,1.0,2.0);
  graphButton("Check .cor",createorderedlist ,1.0,4.0);
  graphButton("Clean .cor",cleancor ,1.0,6.0);
  graphButton("Force Update .cor",dooverwrite, 1.0,8.0);

  abox = graphTextEntry(clonecheck, 14, 1.0, 10.0,printclone);

  graphRedraw();
}
